﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Threading;

using LorraineSec.Libraries.Sensors;
using LorraineSec.DatabaseLib.DataObjects;

namespace LorraineSec.ServerApplication
{
    public partial class AddDeviceForm : Form
    {
        private delegate void TSClose();
        private delegate void TSOutputText(string txt);
        public delegate void DeviceAddCallback(AddDeviceInfo info);

        public static void ShowAddDevicePrompt(string dName, uint compID, DeviceAddCallback call)
        {
            AddDeviceForm form = new AddDeviceForm(dName, compID, call);
            form.Show();
            form.init();
        }

        public struct AddDeviceInfo
        {
            public Sensor SensorLibrary;
            public uint LibID;
            public uint CompartmentID;
            public string Name;
            public string Type;
            public string Serial;
        }
        private AddDeviceInfo AddInfo;
        private DeviceAddCallback Callback;

        private AddDeviceForm(string name, uint compID, DeviceAddCallback call)
        {
            InitializeComponent();
            this.KeyPreview = true;
            
            AddInfo.Name = name;
            AddInfo.CompartmentID = compID;
            Callback = call;
        }

        private void init()
        {
            if (Callback != null)
            {
                Sensor.InitDevLibTypes();
                Sensor.SensorType[] list = Sensor.SensorTypeIDMap.Keys.ToArray();
                //Request user to select the device library
                Sensor.SensorType libType = (Sensor.SensorType)ListSelectForm.getSelectionFromList("Select Library", list, 0);
                if (libType != null)
                {
                    //Get the ID of the library
                    AddInfo.LibID = Sensor.SensorTypeIDMap[libType];
                    //Initialize the library and subscribe
                    AddInfo.SensorLibrary = (Sensor)System.Activator.CreateInstance((Type)libType);
                    AddInfo.SensorLibrary.subscribe(DeviceFeedBack);
                    AddInfo.SensorLibrary.initiate();
                    OutputText("Waiting for device connect");
                    return;
                }
            }
            Close();
        }

        private void DeviceFeedBack(SensorFrame frame)
        {
            //Parse Information from frame
            string outStr = ASCIIEncoding.ASCII.GetString((byte[])frame.Data);
            OutputText("Device Feedback: " + outStr);
            //Is this an attach event
            if (outStr.StartsWith(Sensor.TYPE_ATTACH))
            {
                outStr = outStr.Remove(0, Sensor.TYPE_ATTACH.Length);
                int split = outStr.IndexOf(Sensor.SPLIT_CHAR);
                AddInfo.Serial = outStr.Substring(0, split);
                AddInfo.Type = outStr.Substring(split + 1);

                //Unsubscribe from the library
                AddInfo.SensorLibrary.unsubscribe(DeviceFeedBack);
                //Notify callback
                Callback.BeginInvoke(AddInfo, null, null);
                this.BeginInvoke(new TSClose(Close));
            }
        }

        private void OutputText(string str)
        {
            if (this.InvokeRequired)
                this.Invoke(new TSOutputText(TS_output), new object[] { str });
            else
                TS_output(str);
        }

        private void TS_output(string str)
        {
            OutputTextEdit.AppendText(str + "\n");
            OutputTextEdit.SelectionStart = OutputTextEdit.Text.Length;
            OutputTextEdit.ScrollToCaret();
        }

        private void terminate()
        {
            if(AddInfo.SensorLibrary != null)
                AddInfo.SensorLibrary.shutdown();
        }

        private void CancelButton_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    terminate();
                    Close();
                    break;
            }
        }
    }
}
